<template>
	<view>
		<view class="raffle-wheel" :style="{ width: canvasWidth + 110 + 'rpx', height: canvasHeight + 110 + 'rpx' }">
			<view class="raffle-wheel-wrap" :style="{ width: canvasWidth + 'rpx', height: canvasHeight + 'rpx' }">
				<canvas :class="className" :canvas-id="canvasId" :width="canvasWidth" :height="canvasHeight" :style="{
					width: canvasWidth + 'px',
					height: canvasHeight + 'px'
				}" />
				<image class="canvas-img" :src="canvasImg" :style="{
					width: canvasWidth-5 + 'rpx',
					height: canvasHeight-5 + 'rpx',
					transform: `rotate(${canvasAngle + targetAngle}deg)`,
					transitionDuration: `${transitionDuration}s`,
					'--marginTop':rpxToPx(marginTop),
					'--marginLeft':rpxToPx(marginLeft)
				}" v-if="canvasImg"></image>
				<view class="raffle-wheel__action" @click="handleAction"></view>
				<!-- 为了兼容 app 端 ctx.measureText 所需的标签 -->
				<text class="raffle-wheel__measureText">{{ measureText }}</text>
			</view>

		</view>
		<!-- <text>
			{{screenHeight}}----{{screenWidth}}-----{{pixelRatio}}
		</text> -->
	</view>
</template>

<script>
	// var upng = require('../../utils/UPNG.js');
	export default {
		name: 'RaffleWheel',
		props: {
			// canvas 宽度
			canvasWidth: {
				type: Number,
				default: 240
			},
			// canvas 高度
			canvasHeight: {
				type: Number,
				default: 240
			},
			// 奖品列表
			prizeList: {
				type: Array,
				// 必须是偶数
				validator: function(value) {
					return value.length % 2 === 0;
				},
				required: true
			},
			// 奖品区块对应背景颜色
			colors: {
				type: Array,
				default: () => ['#CA9DF1', '#8133D2'],
				// 必须是偶数且仅为 2 个颜色相互交替
				validator: function(value) {
					return value.length === 2;
				}
			},
			// 旋转动画时间 单位s
			duration: {
				type: Number,
				default: 8
			},
			// 旋转的圈数
			ringCount: {
				type: Number,
				default: 8
			},
			// 字体颜色
			fontColor: {
				// type: String,
				// default: '#A34533'
				type: Array,
				default: () => ['#8133D2', '#CA9DF1'],
				// 必须是偶数且仅为 2 个颜色相互交替
				validator: function(value) {
					return value.length === 2;
				}
			},
			// 文字的大小
			fontSize: {
				type: String,
				default: '30px'
			},
			// 奖品文字多行情况下的行高
			lineHeight: {
				type: Number,
				default: 34
			},
			// 奖品名称所对应的 key 值
			strKey: {
				type: String,
				required: true
			},
			// 奖品文字总长度限制
			strMaxLength: {
				type: Number,
				default: 7
			},
			// 奖品文字多行情况下第一行文字长度
			strLineLength: {
				type: Number,
				default: 4
			}
		},
		data() {
			return {
				// 画板className
				className: 'raffle-wheel__canvas',
				// 画板标识
				canvasId: 'raffleWheelCanvas',
				// 画板导出的图片
				canvasImg: '',
				// 旋转到奖品目标需要的角度
				targetAngle: 0,
				// 旋转动画时间 单位 s
				transitionDuration: 0,
				// 是否正在旋转
				isRotate: false,
				// 当前停留在那个奖品的序号
				stayIndex: 0,
				// 解决 app 不支持 measureText 的问题
				measureText: '',
				// marginTop 判断他的高宽来改变他的margin
				marginTop: 0,
				// marginleft 判断他的高宽来改变他的margin
				marginLeft: 0,
				screenHeight: '',
				screenWidth: '',
				pixelRatio: ''
			};
		},
		computed: {
			// 主要目的就是为了适配rpx
			rpxToPx() {
				// 假设设计稿宽度是750px
				const designWidth = 750;
				// 获取当前屏幕宽度（uni.getSystemInfoSync()是uni-app提供的API）
				const screenWidth = uni.getSystemInfoSync().windowWidth;
				// 计算转换比例
				const ratio = screenWidth / designWidth;
				// 返回转换函数
				return function(rpx) {
					return rpx * ratio + 'px';
				};
			},
			// 设备像素密度
			pixelRatio() {
				return uni.getSystemInfoSync().pixelRatio;
			},
			// 根据奖品列表计算 canvas 旋转角度
			// 让 启动按钮指针 在奖品分区中间 position = 45
			// 让 启动按钮指针 在奖品分区边界 position = 90
			canvasAngle() {
				let prizeCount = this.prizeList.length;
				let position = 90;
				if (prizeCount % 4 !== 0) {
					return 0;
				} else {
					let num = prizeCount / 4;
					return num % 2 === 0 ? position / num : position;
				}
			},
			// 根据画板的宽度计算奖品文字与中心点的距离
			textRadius() {
				return Math.round(this.canvasWidth / 3.2);
			}
		},

		methods: {

			// 判断机型

			judgeBrand(sUserAgent) {
				var isIphone = sUserAgent.match(/iphone/i) == "iphone";
				var isHuawei = sUserAgent.match(/huawei/i) == "huawei";
				var isHonor = sUserAgent.match(/honor/i) == "honor";
				var isOppo = sUserAgent.match(/oppo/i) == "oppo";
				var isOppoR15 = sUserAgent.match(/pacm00/i) == "pacm00";
				var isVivo = sUserAgent.match(/vivo/i) == "vivo";
				var isXiaomi = sUserAgent.match(/mi\s/i) == "mi ";
				var isXiaomi2s = sUserAgent.match(/mix\s/i) == "mix ";
				var isRedmi = sUserAgent.match(/redmi/i) == "redmi";
				var isSamsung = sUserAgent.match(/sm-/i) == "sm-";

				if (isIphone) {
					return 'iphone';
				} else if (isHuawei || isHonor) {
					return 'huawei';
				} else if (isOppo || isOppoR15) {
					return 'oppo';
				} else if (isVivo) {
					return 'vivo';
				} else if (isXiaomi || isRedmi || isXiaomi2s) {
					return 'xiaomi';
				} else if (isSamsung) {
					return 'samsung';
				} else {
					return 'default';
				}
			},


			// 开始旋转
			handleStartRotate(targetIndex) {
				// 奖品总数
				let prizeCount = this.prizeList.length;
				let baseAngle = 360 / prizeCount;
				let angles = 0;
				if (this.targetAngle === 0) {
					console.log('第一次旋转');
					// 因为第一个奖品是从0°开始的，即水平向右方向
					// 第一次旋转角度 = 270度 - (停留的序号-目标序号) * 每个奖品区间角度 - 每个奖品区间角度的一半 - canvas自身旋转的度数
					angles = 270 - (targetIndex - this.stayIndex) * baseAngle - baseAngle / 2 - this.canvasAngle;
				} else {
					console.log('后续旋转');
					// 后续继续旋转 就只需要计算停留的位置与目标位置的角度
					angles = -(targetIndex - this.stayIndex) * baseAngle;
				}
				// 更新目前序号
				this.stayIndex = targetIndex;
				// 转 8 圈，圈数越多，转的越快
				this.targetAngle += angles + 360 * this.ringCount;

				// 计算转盘结束对时间，预加一些延迟确保转盘停止后触发结束事件
				let endTime = this.transitionDuration * 1000 + 100;
				setTimeout(() => {
					console.log('isRotate2:', this.isRotate);
					this.isRotate = false;
					this.$emit('actionEnd');
				}, endTime);
			},
			// 点击 开始抽奖 按钮
			handleAction() {
				console.log('isRotate:', this.isRotate);
				if (this.isRotate) return;
				this.isRotate = true;
				this.$emit('actionStart');
			},
			// 渲染转盘
			async drawWheelCanvas() {
				// 获取 canvas 画布
				const canvasId = this.canvasId;
				const ctx = uni.createCanvasContext(canvasId, this);

				// canvas 的宽高
				let canvasW = this.canvasWidth;
				let canvasH = this.canvasHeight;

				// 根据奖品个数计算 角度
				let prizeCount = this.prizeList.length;
				let baseAngle = (Math.PI * 2) / prizeCount;

				// 设置描边颜色
				// ctx.strokeStyle = '#CE9660';
				ctx.strokeStyle = '#FDD14C';

				// 设置字号字体，Canvas 文本字号字体的默认值是 10px sans-serif，这里必须对 字号 字体 同时覆盖
				let family =
					"-apple-system, BlinkMacSystemFont, 'PingFang SC', 'Helvetica Neue', STHeiti, 'Microsoft Yahei', Tahoma, Simsun, sans-serif";
				ctx.font = `${this.fontSize} ${family}`;

				// 注意，开始画的位置是从0°角的位置开始画的。也就是水平向右的方向。
				// 画具体内容
				for (let i = 0; i < prizeCount; i++) {
					// 当前角度
					let angle = i * baseAngle;

					// 保存当前画布的状态
					ctx.save();

					// 开始画内容
					ctx.beginPath();

					// 开始画圆弧
					// x => 圆弧对应的圆心横坐标 x
					// y => 圆弧对应的圆心横坐标 y
					// radius => 圆弧的半径大小
					// startAngle => 圆弧开始的角度，单位是弧度
					// endAngle => 圆弧结束的角度，单位是弧度
					// anticlockwise(可选) => 绘制方向，true 为逆时针，false 为顺时针
					let outsideRadius = canvasW / 2;
					let insideRadius = 20;
					ctx.arc(canvasW * 0.5, canvasH * 0.5, outsideRadius, angle, angle + baseAngle, false);
					ctx.arc(canvasW * 0.5, canvasH * 0.5, insideRadius, angle + baseAngle, angle, true);

					// 开始链接线条
					ctx.stroke();
					// 每个奖品区块背景填充颜色
					ctx.fillStyle = this.colors[i % 2];
					// 填充颜色
					ctx.fill();

					// 开始绘制奖品内容
					ctx.fillStyle = this.fontColor[i % 2];
					let rewardName = this.strLimit(this.prizeList[i][this.strKey]);

					// translate方法重新映射画布上的 (0,0) 位置
					let translateX = canvasW * 0.5 + Math.cos(angle + baseAngle / 2) * this.textRadius;
					let translateY = canvasH * 0.5 + Math.sin(angle + baseAngle / 2) * this.textRadius;
					ctx.translate(translateX, translateY);

					// rotate方法旋转当前的绘图，因为文字是和当前扇形中心线垂直的
					ctx.rotate(angle + baseAngle / 2 + Math.PI / 2);

					// 设置文本位置并处理换行

					// 是否需要换行
					let isLineBreak = rewardName.length > this.strLineLength;
					if (isLineBreak) {
						// 获得多行文本数组
						rewardName = rewardName.substring(0, this.strLineLength) + ',' + rewardName.substring(this
							.strLineLength);
						let rewardNames = rewardName.split(',');

						// 循环文本数组，计算每一行的文本宽度
						for (let j = 0; j < rewardNames.length; j++) {
							if (ctx.measureText && ctx.measureText(rewardNames[j]).width) {
								// 文本的宽度信息
								let tempStrSize = ctx.measureText(rewardNames[j]);
								ctx.fillText(rewardNames[j], -tempStrSize.width / 2, j * this.lineHeight);
							} else {
								this.measureText = rewardNames[j];

								// 等待页面重新渲染
								await this.$nextTick();

								let textWidth = await this.getTextWidth();

								ctx.fillText(rewardNames[j], -textWidth / 2, j * this.lineHeight);
								console.log(rewardNames[j], textWidth, i);
							}
						}
					} else {
						if (ctx.measureText && ctx.measureText(rewardName).width) {
							// 文本的宽度信息
							let tempStrSize = ctx.measureText(rewardName);
							ctx.fillText(rewardName, -tempStrSize.width / 2, 0);
						} else {
							this.measureText = rewardName;

							// 等待页面重新渲染
							await this.$nextTick();

							let textWidth = await this.getTextWidth();

							ctx.fillText(rewardName, -textWidth / 2, 0);
						}
					}

					ctx.restore();
				}

				// 保存绘图并导出图片
				ctx.draw(true, () => {
					let drawTimer = setTimeout(() => {
						clearTimeout(drawTimer);
						drawTimer = null;

						// wx.canvasGetImageData({
						// 	canvasId: this.canvasId,
						// 	x: 0,
						// 	y: 0,
						// 	width: this.canvasWidth * this.pixelRatio,
						// 	height: this.canvasHeight * this.pixelRatio,
						// 	success: (res)=> {
						// 		// console.log(res)
						// 		let pngData = upng.encode([res.data.buffer], res.width, res.height);
						// 		// let bs64 = wx.arrayBufferToBase64(pngData);
						// 		// this.canvasImg = 'data:image/jgp;base64,' + bs64;
						// 		this.canvasImg = pngData;
						// 		console.log("-------",pngData,this.canvasImg)
						// 		this.$emit('done')
						// 	},
						// 	fail: (err)=> {
						// 		console.log("err",err);
						// 	}
						// },this)

						uni.canvasToTempFilePath({
								destWidth: this.canvasWidth * this.pixelRatio,
								destHeight: this.canvasHeight * this.pixelRatio,
								canvasId: this.canvasId,
								success: res => {
									// 在 H5 平台下，tempFilePath 为 base64
									// console.log("图片", res.tempFilePath)
									// uni.showModal({
									// 	title: '提示',
									// 	content: res.tempFilePath,
									// 	success: function(res) {
									// 		if (res.confirm) {
									// 			console.log('用户点击确定');
									// 		} else if (res.cancel) {
									// 			console.log('用户点击取消');
									// 		}
									// 	}
									// });
									// wx.downloadFile({
									// 	url: res.tempFilePath, //仅为示例，并非真实的资源
									// 	success:(resx)=> {
									// 		console.log('down res', resx);
									// 		this.canvasImg = resx.tempFilePath;
									// 	}
									// });
									// let bs64 = wx.arrayBufferToBase64(res.tempFilePath);
									// this.canvasImg = res.tempFilePath;
									this.canvasImg = res.tempFilePath;
									// 通知父级组件，抽奖转品生成图片完成
									this.$emit('done');
									uni.hideLoading();
								}
							},
							this
						);
					}, 20);
				});
			},
			// 兼容 app 端不支持 ctx.measureText
			// 已知问题：初始绘制时，低端安卓机 平均耗时 2s
			getTextWidth() {
				return new Promise((resolve, reject) => {
					uni.createSelectorQuery()
						.in(this)
						.select('.raffle-wheel__measureText')
						.fields({
								size: true
							},
							res => {
								resolve(res.width);
							}
						)
						.exec();
				});
			},
			// 处理文字溢出
			strLimit(value) {
				let maxLength = this.strMaxLength;
				if (!value || !maxLength) return value;
				return value.length > maxLength ? value.slice(0, maxLength - 1) + '...' : value;
			}
		},
		mounted() {

			var brand = this.judgeBrand(navigator.userAgent.toLowerCase());

			uni.getSystemInfo({
				success: (res) => {
					console.log(res.screenHeight)
					this.screenHeight = res.screenHeight
					this.screenWidth = res.screenWidth
					this.pixelRatio = res.pixelRatio
					console.log(res.screenWidth)
					console.log(res)
					if (res.screenHeight <= 667 && res.screenHeight >= 568 && res.screenWidth >= 320 && res
						.screenWidth <= 375) {
						this.marginTop = 0
						this.marginLeft = -7
					}

					if (res.screenHeight >= 736 && res.screenHeight <= 820 && res.screenWidth <= 414 && res
						.screenWidth >= 375 && res.pixelRatio == 3) {
						this.marginTop = 5
						this.marginLeft = 8
					}

					if (res.screenHeight >= 736 && res.screenHeight <= 820 && res.screenWidth <= 414 && res
						.screenWidth >= 375 && res.pixelRatio > 2&& res.pixelRatio<3) {
			 		this.marginTop = 3
						this.marginLeft = -8
					}
			
					if (res.screenHeight >= 896 && res.screenHeight <= 930 && res.screenWidth >= 380 && res
						.screenWidth <= 420 && res.pixelRatio == 2) {
						this.marginTop = 3
						this.marginLeft = -7
					}
					if (res.screenHeight >= 896 && res.screenHeight <= 930 && res.screenWidth >= 380 && res
						.screenWidth <= 420 && res.pixelRatio == 3) {
						this.marginTop = 5
						this.marginLeft = 8
					}
					if (res.screenHeight >= 896 && res.screenHeight <= 930 && res.screenWidth >= 380 && res
						.screenWidth <= 420 && res.pixelRatio > 3) {
						this.marginTop = 5
						this.marginLeft = 5
					}
				
				}
			})


			console.log(brand)
			uni.showLoading({
				title: '加载中...',
				mask: true
			});
			this.$nextTick(() => {
				let stoTimer = setTimeout(() => {
					clearTimeout(stoTimer);
					stoTimer = null;

					this.drawWheelCanvas();
					this.transitionDuration = this.duration;
				}, 50);
			});
		}
	};
</script>

<style lang="scss" scoped>
	$actionBgUrl: '~static/raffle-wheel/raffle-wheel__action';
	$raffleBgUrl: '~static/raffle-wheel/raffle-wheel__bg';

	.raffle-wheel {
		position: relative;
		left: 0;
		top: 0;
		display: flex;
		justify-content: center;
		align-items: center;
		width: 578rpx;
		height: 578rpx;
	}

	.raffle-wheel {
		display: flex;
		justify-content: center;
		align-items: center;
		margin: 0 auto;
		background-repeat: no-repeat;
		background-position: center center;
		background-size: contain;
		background-image: url($raffleBgUrl+'.png');

		@media (-webkit-min-device-pixel-ratio: 2),
		(min-device-pixel-ratio: 2) {
			background-image: url($raffleBgUrl+'2x.png');
		}

		@media (-webkit-min-device-pixel-ratio: 3),
		(min-device-pixel-ratio: 3) {
			background-image: url($raffleBgUrl+'3x.png');
		}
	}

	.raffle-wheel__canvas {
		position: absolute;
		left: -9999px;
		opacity: 0;
		display: flex;
		justify-content: center;
		align-items: center;
	}

	.raffle-wheel__action {
		position: absolute;
		top: calc(50% - 58px);
		left: calc(50% - 58px);
		width: 114px;
		height: 114px;
		background-repeat: no-repeat;
		background-position: center center;
		background-size: contain;
		background-image: url($actionBgUrl+'.png');

		@media (-webkit-min-device-pixel-ratio: 2),
		(min-device-pixel-ratio: 2) {
			background-image: url($actionBgUrl+'2x.png');
		}

		@media (-webkit-min-device-pixel-ratio: 3),
		(min-device-pixel-ratio: 3) {
			background-image: url($actionBgUrl+'3x.png');
		}
	}

	.raffle-wheel__measureText {
		position: absolute;
		left: 0;
		top: 0;
		white-space: nowrap;
		font-size: 12px;
		opacity: 0;
	}

	.canvas-img {
		z-index: 0;
		transition: transform cubic-bezier(0.34, 0.12, 0.05, 0.95);
		margin-top: var(--marginTop);
		margin-left: var(--marginLeft);
	}
</style>
